<?php

namespace App\Services;

use Goutte\Client as GoutteClient;
use App\Exceptions\InvalidURLException;
use Symfony\Component\DomCrawler\Crawler;

class URLService
{
    /**
     * An URL to crawl.
     *
     * @var string
     */
    protected $url;

    /**
     * An HTTP client.
     */
    protected $client;

    /**
     * A DOM crawler.
     */
    protected $crawler;

    /**
     * URL setter
     *
     * @param string $url
     */
    public function setURL(string $url)
    {
        $this->url = $url;
    }

    /**
     * Client getter
     *
     * @return GoutteClient
     */
    public function getClient()
    {
        if (!$this->client) {
            $this->client = new GoutteClient();
        }

        return $this->client;
    }

    /**
     * Client setter
     *
     * @param GoutteClient $client
     */
    public function setClient(GoutteClient $client)
    {
        $this->client = $client;
    }

    /**
     * DOM crawler getter
     *
     * @return Crawler
     * @throws InvalidURLException
     */
    public function getCrawler(): Crawler
    {
          if (!$this->crawler) {
              try {
                  $this->crawler = $this->getClient()->request('GET', $this->url);
              } catch (\Exception $e) {
                  throw new InvalidURLException("Invalid URL", 400);
              }
          }

          return $this->crawler;
    }

    /**
     * Return destination URL.
     *
     * It should be follows redirects.
     *
     * @return string
     */
    public function getURL(): string
    {
        return $this->getCrawler()->getUri();
    }

    /**
     * Get page title.
     *
     * @return string
     */
    public function getTitle(): string
    {
        try {
            $title = $this->getCrawler()->filter('title')->text();
        } catch (\Exception $e) {
            $title = 'No title found';
        }

        return $title;
    }

    /**
     * Get page description.
     *
     * @return string
     */
    public function getDescription()
    {
        try {
            $description = $this->getCrawler()->filterXpath('//meta[@name="description"]')
                ->attr('content');
        } catch (\Exception $e) {
            $description = 'No description found';
        }

        return $description;
    }
}
